Geckoの最近のブログ記事

初期化済変数はエクスポートできなかっただけという話。 未初期化の変数をエクスポートしてロード時に代入すればOK。 首の皮1枚でつながった。

まあ俺自身は本当にできるかどうかの確認まではしてないけどな。

オワタ\(^O^)/

ことの始まりは「俺のライブラリがFirefox4で使えない(意訳・超要約)」なるメールが届いたこと。 どうやらFirefox4からはXPCOMコンポーネントの呼び出し方法が若干変わるようだ。 で、XPCOM changes in Gecko 2.0を調べてみると、どうもDLLから変数のエクスポートをしなければならないらしい。 だが、Delphiは関数のエクスポートはできても変数のエクスポートができない。

はい、終了。

もともと最近は興味が縮小して放置状態だったとはいえ、この変更は致命的な致命傷だ。 何とかしたいところだが現状では前の方法に戻してくれとコミットするしかないな。 こんな理由でBugzilla初投稿なるのか?いやだなあ。

GeckoSDK for DelphiのコードをBagelブラウザによる変更を一部マージするなどして更新した。 Begelの新バージョンはDelphiを使わないようなので、もう更新は俺が頑張るしかないんだよな。

それはそうとBegelがDelphiの採用をやめた理由のひとつに、Mozilla 2でのAPIの大幅変更がある。 C++例外を前提にしたコードになるので、フレームワークのまったく違うDelphiでの対応は確かに難しい。 よほど変態的なコードでラッパを書かないことには新APIでは動かすこともままならないだろう。

で、どんな変態的ラッパを書かねばならないかと、新APIのコードを確認してみたかったのだが、 いかんせんソースツリーにその正体が現れてこない。 Mozilla-centralのコードは旧態依然としたGecko 1.9ベースのコードのままだ。 Mozilla 2のAPIが新しくなるのは2006年には発表されていたので、 かれこれ2年以上もその姿が見えていないことになる。

目標の向かう方向はわかるものの、その行く先がはっきりしないのではどうしようもない。 しばらくはGecko 1.xベースのままでコードは保守されていくだろう。 Gecko 2の開発期間がGecko 1.0より長くなりませんように。

Delphi 2009を買った結果がこれだよ!

若干放置気味になっているGecko SDK for DelphiをDelphi 2009に対応すべく コードの修正を開始した。 しかしこれが大変だ。 Delphi 2009はDelphiで初めてRTLとVCLがすべてUnicode対応にしたため、 というかむしろUnicodeを標準にしたため、 過去のコードの修正が結構大変なことになってきた。 基本ASCII文字列しか扱えないURL周りの処理はともかく、 MBCSでもUnicodeでもどちらでもいけるファイル関係の処理は 今後の設計ポリシーにも関わることなので慎重にいかねばならない。

というかそんなこと考えている暇があるならまずコードの内容を充実させろよ。

Gecko 1.7以前はGeckoの初期化をするために、xpcom.dll内の NS_InitXPCOM2を呼び出す必要があった。 この関数の引数にはnsIDirectoryServiceProviderを指定する必要があり、 しかもこのインターフェースはGREの 場所を返せないといけない。 はっきり行って面倒くさい。 ちゃんと動作させないと一部のインターフェースが動いてくれないので、 面倒くさいが必須の作業なのだ。 まあ面倒くさい。 このインターフェースを含む初期化処理を行う関数を自作ライブラリに用意しているのだが、 初期化用ライブラリのため暗黙の動的メモリ確保を使用するコードを書きたくなかったので、 とても神経を使った。 ていうかNewInstanceクラスメソッドとかはじめて使った。

一方、Gecko 1.8以降には追加関数としてXRE_InitEmbeddingが用意された。 こいつはxul.dll内にある関数なのだが、 非常に面倒くさいnsIDirectoryServiceProviderの実装を 肩代わりしてくれている点において、非常にありがたい。 まあこの関数をxul.dllから持ってくるコードを書かないといけないわけだが、 インターフェースの実装よりははるかに簡単だ。 Gecko内部の関数なので、Geckoの仕様が変わったりとかで初期化の仕方が変わっても、 ちゃんと追従できるのがうれしい。 こういう関数をもっと早く用意してくれれば無駄なコードを核時間が減るんだけどなあ。

そういえば以前nsAStringの実装をDelphiで実現したな。 Gecko 1.7でNS_StringContainerInitその他が実装されたときには、 血の涙を流して喜んだものだ。

nsIWebBrowserのガワの話。 要するにnsIWebBrowserChromeの実装の話。 とりあえず触りだけ。

最低限以下のインターフェースの実装が必要なようだ。

nsIWebBrowserChrome

ガワ本体。ガワなのに本体とはどういうことかと思うが nsIWebBrowser.containerWindownsIWebBrowserChrome型なので仕方ない。

nsIInterfaceRequestor

今ひとつどう説明すればわからないインターフェース。 queryInterfaceによく似たメソッドgetInterfaceを持つ。 getInterfaceで取得したインターフェースは逆変換できる必要はない。 queryInterfaceではあくまで自分自身を返すが、 getInterfaceではプロパティや関数の戻り値を返してもいいことになる。 Mozillaのソースを深く読んではいないのでどう便利なのかはいまいちわからないが、 nsIWebBrowserのガワとしては必須。

とりあえず上の2つのインターフェースのメンバのうち、 nsIInterfaceRequestor.getInterfaceメソッドを queryInterfaceに丸投げして nsIWebBrowserChrome.webBrowserプロパティを実装すれば 残りのメソッドは全部NS_ERROR_NOT_IMPLEMENTEDにしても動く。 getInterfaceを実装しないとFlashもまともに表示されないしリンクも飛べない。 でもgetInterfaceさえ実装すれば動く。 それくらい重要。

はっきり言ってGecko Embedding BasicsnsIInterfaceRequestorがないのは詐欺だろ。

続・nsIHttpChannel.asyncOpenが動かないの続き。

nsIHttpChannel.asyncOpenおよび nsIStreamListenerがらみのソースを追っていったところ、 どうやらNS_ProcessNextEventなる関数が怪しいことがわかった。 この関数は現在のスレッドに対して nsIThread.processNextEvent(PR_False)を呼び出す。 こうすることで現在のスレッドにたまっているGeckoイベントを処理することができるわけだ。 こいつを呼び出す処理をたとえばDelphiならApplication.OnIdleに追加すればいい。

が、Gecko1.8まではそんなことをせずともイベントを処理できていたので改悪に見えなくもない。 せっかくのイベント駆動型のOSを使っているのに こんな余計な処理を埋め込みたくないというのが正直な感想だ。 一応Gecko1.9でもSimpleDownload他を動かせる目処が立ったので、 とりあえずそれはよしとする。

まさかnsIWebBrowserのリスナーでも必要だとか言うことはないだろうな。

30分で「続」とかないわ。

nsIHttpChannel.asyncOpenが動かないの続き。 Mozillaおよびxulrunnerのbinフォルダに直接SimpleDownloadをぶち込んで動作確認をした。

タイトルのごとく。 nsIHttpChannelが動かないわけじゃなくてnsIHttpChannel.asyncOpenが動かない。 nsIHttpChannel.openは問題なく使用可能だったのだが、 nsIHttpChannel.asyncOpenはなぜか動作しない。 引数のaListenerもプロパティのnotificationCallbacksのほうにもgetInterfaceはおろか QueryInterfaceすら呼び出されない。 つまり当然コールバックがないのでデータの読み込みは不可・・・。 SimpleDownloadでも、xpcshellでもだめなので原因がいまいちよくわからない。 SimpleDownloadを作ったときには動いていたので、Geckoのバージョンがあがったので仕様が変わったのだろうか? Frozenインターフェースのはずだからそれはないと思いたい。

以上、メモというより愚痴終わり。

6年位前に通過したことをいまさら記録として残してみるテスト。

begin
  { 初期化 }
  XPCOMGlueStartup(xpcomPath);
  XPCOMGlueLoadXULFunctions(@xulFunctions);
  XRE_InitEmbedding(xpcomDir, nil, nil, nil, 0);

  { WebBrowserオブジェクトの作成 }
  NS_CreateInstance(NS_WEBBROWSER_CONTRACTID, nsIWebBrowser, browser);
  baseWin := browser as nsIBaseWindow;
  baseWin.InitWindow(Pointer(hWnd), nil, 0, 0, rcClient.Right, rcClient.Bottom);
  baseWin.Create();
  baseWin.SetVisibility(PR_True);

  { ページ読み込み }
  navigation := browser as nsINavigation;
  navigation.LoadURI('http://nesitive.net/nesitive/', 0, nil, nil, nil);

  { 気が済んだら終了 }
  XRE_TermEmbedding();
  // XPCOMGlueShutdown(); // なぜかエラーになる
end.

アーカイブ

ウェブページ

Powered by Movable Type 5.02

このアーカイブについて

このページには、過去に書かれたブログ記事のうちGeckoカテゴリに属しているものが含まれています。

前のカテゴリはFreeBSDです。

次のカテゴリはMacです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。